"""
Windows安全审计规则定义 - 详细配置状态版本
"""
import ctypes
import winreg
import subprocess
import re
import time

from datetime import datetime
from typing import Dict, List, Any
import logging

logger = logging.getLogger(__name__)

class WindowsAuditRules:
    """Windows安全审计规则类"""

    @staticmethod
    def run_cmd_simple(command: str) -> str:
        """简化的命令执行，避免编码问题"""
        try:
            result = subprocess.run(
                command,
                shell=True,
                capture_output=True,
                text=True,
                timeout=30,
                encoding='gbk',
                errors='replace'
            )
            return result.stdout
        except subprocess.TimeoutExpired:
            return "Error: 命令执行超时"
        except Exception as e:
            return f"Error: {str(e)}"

    @staticmethod
    def check_password_policy() -> Dict[str, Any]:
        """1. 检查密码策略（修复版）"""
        print("[规则1] 检查密码策略...")
        try:
            # 使用类内的方法
            output = WindowsAuditRules.run_cmd_simple("net accounts")

            # 检查命令是否执行成功
            if "Error" in output or "错误" in output or "语法" in output:
                return {
                    "rule_name": "密码策略检查",
                    "status": "执行失败",
                    "status_details": ["× 命令执行失败"],
                    "recommendation": "请手动运行 'net accounts' 检查密码策略"
                }

            # 逐行分析输出，查找密码长度
            lines = output.split('\n')
            min_length = 0

            for line in lines:
                line = line.strip()
                if "密码长度最小值" in line:
                    # 提取数字
                    numbers = re.findall(r'\d+', line)
                    if numbers:
                        min_length = int(numbers[0])
                        break

            # 状态判断
            if min_length > 0:
                status_details = [f"✓ 密码最小长度: {min_length}位"]
                status = "通过"
                recommendation = "密码长度已设置"
            else:
                status_details = ["× 未检测到密码长度设置"]
                status = "未通过"
                recommendation = "请设置密码最小长度"

            return {
                "rule_name": "密码策略检查",
                "status": status,
                "status_details": status_details,
                "recommendation": recommendation
            }
        except Exception as e:
            return {
                "rule_name": "密码策略检查",
                "status": "执行失败",
                "status_details": [f"× 命令执行失败: {str(e)}"],
                "recommendation": "请手动运行 'net accounts' 检查密码策略"
            }

    @staticmethod
    def check_user_accounts() -> Dict[str, Any]:
        """2. & 3. 检查用户账户"""
        print("[规则2-3] 检查用户账户...")

        users_output = run_cmd_simple("wmic useraccount get name, sid, disabled /format:csv")
        guest_output = run_cmd_simple("net user guest")

        users = []
        suspicious_users = []
        status_details = []

        # 解析用户账户
        lines = users_output.strip().split('\n')
        for line in lines[1:]:
            if ',' in line and len(line.split(',')) >= 4:
                parts = line.split(',')
                username, sid, disabled = parts[1], parts[2], parts[3] == "TRUE"

                user_info = {"username": username, "disabled": disabled}
                users.append(user_info)

                # 检查可疑账户
                if username.lower() == "guest" and not disabled:
                    suspicious_users.append(f"Guest账户未禁用")
                elif username.lower() not in ["administrator", "guest"] and "admin" in username.lower():
                    suspicious_users.append(f"可疑管理员账户: {username}")

        # Guest账户状态
        guest_enabled = "帐户启用            是" in guest_output
        if guest_enabled:
            suspicious_users.append("Guest账户已启用")

        # 构建详细状态
        status_details.append(f"✓ 总用户账户数: {len(users)}")
        status_details.append(f"✓ 已禁用账户: {sum(1 for u in users if u['disabled'])}个")

        if not suspicious_users:
            status_details.append("✓ 未发现可疑影子账户")
            status_details.append("✓ Guest账户已正确配置")
        else:
            for issue in suspicious_users:
                status_details.append(f"✗ {issue}")

        return {
            "rule_name": "用户账户检查",
            "status": "正常" if not suspicious_users else "异常",
            "config_status": {
                "total_users": len(users),
                "disabled_users": sum(1 for u in users if u['disabled']),
                "suspicious_accounts": suspicious_users,
                "guest_enabled": guest_enabled
            },
            "status_details": status_details,
            "recommendation": "用户账户配置正常" if not suspicious_users else "建议禁用Guest账户和检查可疑管理员账户"
        }

    @staticmethod
    def check_administrator_group() -> Dict[str, Any]:
        """4. 检查Administrator组成员"""
        print("[规则4] 检查管理员组成员...")
        output = run_cmd_simple("net localgroup administrators")

        members = []
        start_collecting = False

        for line in output.strip().split('\n'):
            if "命令成功完成" in line:
                break
            if "----" in line:
                start_collecting = True
                continue
            if start_collecting and line.strip() and not line.startswith('#'):
                username = line.strip()
                if username and username not in ["Administrators", "成员", "----"]:
                    members.append(username)

        # 详细状态描述
        status_details = []
        status_details.append(f"✓ 管理员组成员数量: {len(members)}")

        for member in members:
            if member.lower() == "guest":
                status_details.append(f"✗ 高危: Guest用户存在于管理员组")
            else:
                status_details.append(f"✓ 成员: {member}")

        risk_assessment = "低风险" if len(members) <= 3 and "Guest" not in members else "高风险"

        return {
            "rule_name": "管理员组成员检查",
            "status": "正常" if risk_assessment == "低风险" else "异常",
            "config_status": {
                "member_count": len(members),
                "members": members,
                "risk_assessment": risk_assessment
            },
            "status_details": status_details,
            "recommendation": "管理员组配置合理" if risk_assessment == "低风险" else "建议移除不必要的管理员组成员"
        }

    @staticmethod
    def check_audit_logs() -> Dict[str, Any]:
        """5. 检查日志审计"""
        print("[规则5] 检查日志审计...")

        logs_to_check = ["security", "system", "application"]
        log_status = {}
        status_details = []

        for log_name in logs_to_check:
            output = run_cmd_simple(f"wevtutil gl {log_name} | findstr enabled")
            enabled = "enabled: true" in output.lower()
            log_status[log_name] = enabled

            if enabled:
                status_details.append(f"✓ {log_name}日志: 已启用")
            else:
                status_details.append(f"✗ {log_name}日志: 未启用")

        all_enabled = all(log_status.values())

        return {
            "rule_name": "日志审计检查",
            "status": "正常" if all_enabled else "异常",
            "config_status": {
                "security_log": log_status.get("security", False),
                "system_log": log_status.get("system", False),
                "application_log": log_status.get("application", False)
            },
            "status_details": status_details,
            "recommendation": "所有关键日志审计已启用" if all_enabled else "建议启用所有安全审计日志"
        }

    @staticmethod
    def check_backup_status() -> Dict[str, Any]:
        """6. 检查备份状态"""
        print("[规则6] 检查备份状态...")

        backup_tasks = run_cmd_simple('schtasks /query /fo table | findstr /i "backup"')
        backup_tasks_found = len(backup_tasks.strip()) > 0 and "信息" not in backup_tasks

        status_details = []
        if backup_tasks_found:
            status_details.append("✓ 发现备份相关计划任务")
            # 提取备份任务详情
            task_lines = [line.strip() for line in backup_tasks.split('\n') if line.strip()]
            for task in task_lines[:3]:  # 显示前3个任务
                status_details.append(f"  - 备份任务: {task}")
        else:
            status_details.append("✗ 未发现明显的备份计划任务")

        return {
            "rule_name": "备份状态检查",
            "status": "正常" if backup_tasks_found else "需确认",
            "config_status": {
                "backup_tasks_found": backup_tasks_found,
                "automatic_backup": backup_tasks_found
            },
            "status_details": status_details,
            "recommendation": "发现自动备份任务" if backup_tasks_found else "建议配置定期系统备份策略"
        }

    @staticmethod
    def check_updates_status() -> Dict[str, Any]:
        """7. 检查系统更新状态"""
        print("[规则7] 检查系统更新状态...")

        updates_output = run_cmd_simple("wmic qfe list brief | sort /+70 /r")

        # 分析更新信息
        update_lines = [line.strip() for line in updates_output.strip().split('\n') if line.strip()]
        recent_updates = []
        status_details = []

        if len(update_lines) > 1:
            # 获取最近5个更新
            for i, line in enumerate(update_lines[1:6]):  # 跳过标题行，取前5个
                parts = line.split()
                if len(parts) >= 2:
                    update_id = parts[0]
                    update_date = parts[-1]
                    recent_updates.append({"id": update_id, "date": update_date})

            status_details.append(f"✓ 最近系统更新数量: {len(update_lines)-1}个")
            status_details.append("✓ 最近5个更新:")
            for update in recent_updates:
                status_details.append(f"  - {update['id']} ({update['date']})")
        else:
            status_details.append("✗ 未找到系统更新记录")

        has_recent_updates = len(update_lines) > 10  # 假设有10个以上更新算正常

        return {
            "rule_name": "系统更新检查",
            "status": "正常" if has_recent_updates else "需检查",
            "config_status": {
                "total_updates": len(update_lines) - 1 if len(update_lines) > 1 else 0,
                "update_frequency": "正常" if has_recent_updates else "可能长时间未更新"
            },
            "status_details": status_details,
            "recommendation": "系统更新状态正常" if has_recent_updates else "建议检查并安装系统更新"
        }

    @staticmethod
    def check_services_and_ports() -> Dict[str, Any]:
        """8. 检查服务和端口 - 增强版（明确标注建议关闭项）"""
        print("[规则8] 检查服务和端口...")

        status_details = []

        # 1. 检查监听端口
        ports_output = run_cmd_simple("netstat -ano -p tcp | findstr LISTENING")
        listening_ports = [line.strip() for line in ports_output.strip().split('\n') if line.strip()]

        status_details.append(f"✓ 当前TCP TCP监听 TCP监听端口总数: {len(listening_ports)}")
        status_details.append("  监听端口详情:")
        for i, port_line in enumerate(listening_ports, 1):
            status_details.append(f"    {i:2d}. {port_line}")

        # 2. 高危端口定义（明确建议关闭）
        high_risk_ports = {
            "21": {"desc": "FTP (明文传输，易被窃听)", "suggestion": "关闭FTP服务，改用SFTP"},
            "23": {"desc": "Telnet (明文认证，极不安全)", "suggestion": "立即关闭，改用SSH"},
            "135": {"desc": "RPC (远程过程调用，常被攻击利用)", "suggestion": "禁用RPC服务或限制访问"},
            "139": {"desc": "NetBIOS (文件共享，易被枚举)", "suggestion": "关闭文件和打印机共享"},
            "445": {"desc": "SMB (永恒之蓝等漏洞高发)", "suggestion": "禁用SMBv1，限制访问或关闭"},
            "3389": {"desc": "RDP (远程桌面，暴力破解目标)", "suggestion": "关闭或改为非默认端口并限制IP"},
            "1433": {"desc": "SQL Server (数据库端口，易被攻击)", "suggestion": "限制仅内部IP访问"},
            "3306": {"desc": "MySQL (数据库端口，暴露风险高)", "suggestion": "限制仅内部IP访问"},
            "5432": {"desc": "PostgreSQL (数据库端口，需保护)", "suggestion": "限制仅内部IP访问"}
        }

        risky_ports_found = []
        for port_line in listening_ports:
            for port, info in high_risk_ports.items():
                if f":{port} " in port_line:
                    risky_ports_found.append({
                        "port": port,
                        "desc": info["desc"],
                        "suggestion": info["suggestion"]
                    })

        if risky_ports_found:
            status_details.append("\n✗ 发现以下高危端口（建议关闭/限制）:")
            for i, port_info in enumerate(risky_ports_found, 1):
                status_details.append(f"    {i:2d}. 端口 {port_info['port']}: {port_info['desc']}")
                status_details.append(f"       建议: {port_info['suggestion']}")
        else:
            status_details.append("\n✓ 未发现常见高危端口")

        # 3. 高危服务定义（明确建议关闭）
        high_risk_services = {
            "RemoteRegistry": {
                "desc": "远程注册表服务（允许远程修改注册表）",
                "suggestion": "设置为“禁用”，命令: sc config RemoteRegistry start= disabled"
            },
            "TlntSvr": {
                "desc": "Telnet服务（明文传输，极不安全）",
                "suggestion": "立即卸载或禁用，命令: sc config TlntSvr start= disabled"
            },
            "upnphost": {
                "desc": "UPnP设备主机（易被端口映射攻击）",
                "suggestion": "禁用，命令: sc config upnphost start= disabled"
            },
            "SSDPSRV": {
                "desc": "SSDP发现服务（易被DDoS反射攻击）",
                "suggestion": "禁用，命令: sc config SSDPSRV start= disabled"
            },
            "FDResPub": {
                "desc": "功能发现资源发布（暴露网络资源）",
                "suggestion": "禁用，命令: sc config FDResPub start= disabled"
            },
            "LanmanServer": {
                "desc": "文件共享服务(SMB)（漏洞高发）",
                "suggestion": "非必要则禁用，命令: sc config LanmanServer start= disabled"
            }
        }

        # 需谨慎处理的服务（不建议直接关闭，但需限制）
        cautious_services = {
            "TermService": {
                "desc": "远程桌面服务（必要时使用，需加固）",
                "suggestion": "修改默认端口3389，启用网络级别认证，限制IP访问"
            },
            "WinRM": {
                "desc": "Windows远程管理（PowerShell远程）",
                "suggestion": "限制仅信任IP访问，启用HTTPS加密"
            }
        }

        running_risky_services = []
        running_cautious_services = []
        # 检查高危服务状态
        for service, info in high_risk_services.items():
            output = run_cmd_simple(f"sc query {service}")
            if "RUNNING" in output:
                running_risky_services.append({
                    "service": service,
                    "desc": info["desc"],
                    "suggestion": info["suggestion"]
                })
        # 检查需谨慎处理的服务状态
        for service, info in cautious_services.items():
            output = run_cmd_simple(f"sc query {service}")
            if "RUNNING" in output:
                running_cautious_services.append({
                    "service": service,
                    "desc": info["desc"],
                    "suggestion": info["suggestion"]
                })

        if running_risky_services:
            status_details.append("\n✗ 发现以下高危服务（建议立即关闭）:")
            for i, srv_info in enumerate(running_risky_services, 1):
                status_details.append(f"    {i:2d}. 服务 {srv_info['service']}: {srv_info['desc']}")
                status_details.append(f"       操作: {srv_info['suggestion']}")
        else:
            status_details.append("\n✓ 未发现需立即关闭的高危服务")

        if running_cautious_services:
            status_details.append("\n⚠️ 发现以下需谨慎处理的服务（建议加固）:")
            for i, srv_info in enumerate(running_cautious_services, 1):
                status_details.append(f"    {i:2d}. 服务 {srv_info['service']}: {srv_info['desc']}")
                status_details.append(f"       加固: {srv_info['suggestion']}")

        # 风险评估
        risk_level = "低风险"
        if len(risky_ports_found) > 1 or len(running_risky_services) > 0:
            risk_level = "中风险"
        if len(risky_ports_found) > 3 or len(running_risky_services) > 2:
            risk_level = "高风险"

        return {
            "rule_name": "服务端口检查",
            "status": "异常" if risk_level in ["中风险", "高风险"] else "正常",
            "config_status": {
                "total_listening_ports": len(listening_ports),
                "high_risk_ports": [p["port"] for p in risky_ports_found],
                "risky_services_to_close": [s["service"] for s in running_risky_services],
                "cautious_services_to_harden": [s["service"] for s in running_cautious_services],
                "risk_assessment": risk_level
            },
            "status_details": status_details,
            "recommendation": (
                f"共发现 {len(risky_ports_found)} 个高危端口和 {len(running_risky_services)} 个需关闭的高危服务，"
                f"请按建议执行关闭/限制操作" if risky_ports_found or running_risky_services else
                "端口和服务配置相对安全，定期复查即可"
            )
        }

    @staticmethod
    def check_scheduled_tasks() -> Dict[str, Any]:
        """9. 检查计划任务 - 明确建议删除的可疑自启项"""
        print("[规则9] 检查计划任务...")

        tasks_output = run_cmd_simple("schtasks /query /fo table")

        all_tasks = []
        suspicious_tasks = []  # 建议删除的任务
        microsoft_tasks = []
        status_details = []

        lines = tasks_output.strip().split('\n')
        for line in lines:
            if line.strip() and not line.startswith(('===', '任务名称')):
                parts = line.split()
                if parts:
                    task_name = parts[0]
                    all_tasks.append(task_name)

        status_details.append(f"✓ 总计划任务数量: {len(all_tasks)}")

        # 可疑任务特征（明确建议删除）
        suspicious_patterns = [
            # 路径可疑
            r"c:\\temp", r"c:\\windows\\temp", r"c:\\users\\public",
            # 名称可疑
            r"update\.exe", r"setup\.exe", r"install\.exe", r"run\.exe",
            r"wscript\.exe", r"cscript\.exe", r"powershell\.exe -encodedcommand",
            # 行为可疑
            r"startup", r"persistence", r"backdoor", r"rat", r"keylog"
        ]

        # 微软官方任务（通常安全）
        microsoft_patterns = [
            r"microsoft", r"windows", r"office", r"defender", r"onedrive", r"edge"
        ]

        # 分析任务风险
        for task_name in all_tasks:
            task_lower = task_name.lower()
            is_microsoft = any(p in task_lower for p in microsoft_patterns)
            is_suspicious = any(re.search(p, task_lower) for p in suspicious_patterns)

            if is_suspicious and not is_microsoft:
                # 获取任务执行命令（判断是否为恶意）
                task_detail = run_cmd_simple(f'schtasks /query /tn "{task_name}" /fo list')
                cmd_match = re.search(r"运行命令:\s*(.+)", task_detail)
                cmd = cmd_match.group(1) if cmd_match else "未知命令"

                suspicious_tasks.append({
                    "task_name": task_name,
                    "cmd": cmd,
                    "reason": "包含可疑路径/命令或非微软官方任务"
                })
            elif is_microsoft:
                microsoft_tasks.append(task_name)

        # 输出结果
        status_details.append(f"✓ 微软官方任务数量: {len(microsoft_tasks)}")
        status_details.append(f"✗ 建议删除的可疑任务数量: {len(suspicious_tasks)}")

        if suspicious_tasks:
            status_details.append("\n✗ 以下任务建议立即删除:")
            for i, task in enumerate(suspicious_tasks, 1):
                status_details.append(f"    {i:2d}. 任务名称: {task['task_name']}")
                status_details.append(f"       执行命令: {task['cmd']}")
                status_details.append(f"       原因: {task['reason']}")
                status_details.append(f"       操作: 运行命令删除: schtasks /delete /tn \"{task['task_name']}\" /f")
        else:
            status_details.append("\n✓ 未发现建议删除的可疑任务")

        status_details.append("\n✓ 部分微软官方任务示例:")
        for task in microsoft_tasks[:3]:
            status_details.append(f"    - {task}")

        return {
            "rule_name": "计划任务检查",
            "status": "异常" if suspicious_tasks else "正常",
            "config_status": {
                "total_tasks": len(all_tasks),
                "suspicious_tasks": [t["task_name"] for t in suspicious_tasks],
                "microsoft_tasks_sample": microsoft_tasks[:5]
            },
            "status_details": status_details,
            "recommendation": (
                f"发现 {len(suspicious_tasks)} 个可疑计划任务，可能是恶意自启项，"
                f"请按建议执行删除操作" if suspicious_tasks else
                "计划任务配置正常，无明显恶意自启项"
            )
        }

    # @staticmethod
    # def check_firewall_status() -> Dict[str, Any]:
    #     """10. 检查防火墙状态 - 通过netsh命令实际检测"""
    #     print("[规则10] 检查防火墙状态...")
    #
    #     try:
    #         import subprocess
    #         import re
    #
    #         # 执行netsh命令获取防火墙状态
    #         result = subprocess.run(
    #             ['netsh', 'advfirewall', 'show', 'allprofiles'],
    #             capture_output=True,
    #             text=True,
    #             encoding='utf-8',
    #             errors='ignore'
    #         )
    #
    #         output = result.stdout
    #
    #         # 调试：打印原始输出以便分析
    #         print("防火墙检测原始输出:")
    #         print(output)
    #
    #         # 使用正则表达式直接匹配状态
    #         # 匹配模式：配置文件名称 + 状态行
    #         domain_pattern = r'(域|装)[^\n]*配置[^\n]*\n-+\n状态\s+(启用|开启|关闭)'
    #         private_pattern = r'专用[^\n]*配置[^\n]*\n-+\n状态\s+(启用|开启|关闭)'
    #         public_pattern = r'公用[^\n]*配置[^\n]*\n-+\n状态\s+(启用|开启|关闭)'
    #
    #         # 查找各配置文件状态
    #         domain_match = re.search(domain_pattern, output)
    #         private_match = re.search(private_pattern, output)
    #         public_match = re.search(private_pattern, output)  # 注意：这里应该是public_pattern
    #
    #         # 修正public_match
    #         public_match = re.search(public_pattern, output)
    #
    #         # 设置状态
    #         domain_enabled = domain_match and domain_match.group(2) in ['启用', '开启'] if domain_match else False
    #         private_enabled = private_match and private_match.group(1) in ['启用', '开启'] if private_match else False
    #         public_enabled = public_match and public_match.group(1) in ['启用', '开启'] if public_match else False
    #
    #         # 如果正则匹配失败，使用简单字符串查找
    #         if not any([domain_enabled, private_enabled, public_enabled]):
    #             domain_enabled = '状态    启用' in output or '状态    开启' in output
    #             private_enabled = domain_enabled  # 如果没有明确区分，假设相同状态
    #             public_enabled = domain_enabled
    #
    #         all_enabled = domain_enabled and private_enabled and public_enabled
    #
    #         # 构建状态详情
    #         status_details = []
    #         status_details.append(
    #             f"{'✓' if domain_enabled else '✗'} 域配置文件: {'已开启' if domain_enabled else '已关闭'}")
    #         status_details.append(
    #             f"{'✓' if private_enabled else '✗'} 专用配置文件: {'已开启' if private_enabled else '已关闭'}")
    #         status_details.append(
    #             f"{'✓' if public_enabled else '✗'} 公用配置文件: {'已开启' if public_enabled else '已关闭'}")
    #
    #         # 根据实际状态确定结果
    #         if all_enabled:
    #             status = "正常"
    #             recommendation = "防火墙所有配置文件已正常开启"
    #         else:
    #             status = "异常"
    #             recommendation = "部分或全部防火墙配置文件已关闭，建议开启防火墙以增强系统安全"
    #
    #         print(f"检测结果: 状态={status}")
    #
    #         return {
    #             "rule_name": "防火墙状态检查",
    #             "status": status,
    #             "config_status": {
    #                 "domain_profile": domain_enabled,
    #                 "private_profile": private_enabled,
    #                 "public_profile": public_enabled,
    #                 "all_profiles_enabled": all_enabled
    #             },
    #             "status_details": status_details,
    #             "recommendation": recommendation
    #         }
    #
    #     except Exception as e:
    #         return {
    #             "rule_name": "防火墙状态检查",
    #             "status": "检查失败",
    #             "config_status": {"error": str(e)},
    #             "status_details": [f"检查过程中发生错误: {str(e)}"],
    #             "recommendation": "防火墙状态需要手动验证，请运行 'netsh advfirewall show allprofiles' 命令检查"
    #         }

    @staticmethod
    def check_firewall_status() -> Dict[str, Any]:
        """10. 检查防火墙状态 - 通过netsh命令实际检测"""
        print("[规则10] 检查防火墙状态...")

        try:
            import subprocess
            import re

            # 执行netsh命令获取防火墙状态，不指定编码
            result = subprocess.run(
                ['netsh', 'advfirewall', 'show', 'allprofiles'],
                capture_output=True,
                text=False  # 获取bytes，手动处理编码
            )

            # 尝试多种编码方式
            encodings = ['gbk', 'utf-8', 'cp936', 'latin-1', 'iso-8859-1']
            output = None

            for encoding in encodings:
                try:
                    output = result.stdout.decode(encoding)
                    # 检查是否成功解码（包含可读字符）
                    if any(keyword in output for keyword in ['状态', 'State', '启用', '开启', 'ON', 'OFF']):
                        break
                except UnicodeDecodeError:
                    continue

            # 如果所有编码都失败，使用errors='ignore'
            if output is None:
                output = result.stdout.decode('utf-8', errors='ignore')

            print("防火墙检测原始输出:")
            print(output)

            # 检测系统语言并相应处理
            domain_enabled = False
            private_enabled = False
            public_enabled = False

            # 方法1：检测状态关键词（支持中英文）
            status_keywords = {
                'enabled': ['ON', '启用', '开启'],
                'disabled': ['OFF', '关闭']
            }

            # 检查输出中是否包含状态关键词
            has_enabled = any(keyword in output for keyword in status_keywords['enabled'])
            has_disabled = any(keyword in output for keyword in status_keywords['disabled'])

            # 方法2：使用更简单的状态检测
            # 如果输出中有明确的启用关键词且没有明确的禁用关键词，认为开启
            if has_enabled and not has_disabled:
                domain_enabled = private_enabled = public_enabled = True
            elif has_disabled and not has_enabled:
                domain_enabled = private_enabled = public_enabled = False
            else:
                # 如果两者都有或都没有，使用保守策略
                # 检查配置文件数量
                profile_count = output.count('配置文件') + output.count('Profile')
                if profile_count >= 3 and has_enabled:
                    domain_enabled = private_enabled = public_enabled = True
                else:
                    domain_enabled = private_enabled = public_enabled = False

            # 方法3：如果输出完全乱码，使用命令行返回码判断
            if not output.strip() or len(output) < 50:  # 输出太短或为空
                # 运行一个简单的防火墙状态检查命令
                try:
                    test_result = subprocess.run(
                        ['netsh', 'advfirewall', 'show', 'currentprofile'],
                        capture_output=True,
                        text=False
                    )
                    # 如果命令成功执行，可能防火墙是开启的
                    if test_result.returncode == 0:
                        domain_enabled = private_enabled = public_enabled = True
                    else:
                        domain_enabled = private_enabled = public_enabled = False
                except:
                    domain_enabled = private_enabled = public_enabled = False

            all_enabled = domain_enabled and private_enabled and public_enabled

            # 构建状态详情
            status_details = []
            status_details.append(
                f"{'✓' if domain_enabled else '✗'} 域配置文件: {'已开启' if domain_enabled else '已关闭'}")
            status_details.append(
                f"{'✓' if private_enabled else '✗'} 专用配置文件: {'已开启' if private_enabled else '已关闭'}")
            status_details.append(
                f"{'✓' if public_enabled else '✗'} 公用配置文件: {'已开启' if public_enabled else '已关闭'}")

            # 根据检测结果确定状态
            if all_enabled:
                status = "正常"
                recommendation = "防火墙所有配置文件已正常开启"
            else:
                status = "异常"
                recommendation = "部分或全部防火墙配置文件已关闭，建议开启防火墙以增强系统安全"

            # 添加编码问题提示
            if '״̬' in output or 'ǽ' in output:  # 检测到乱码字符
                recommendation += " (检测到编码问题，结果可能需要人工验证)"

            print(f"检测结果: 域={domain_enabled}, 专用={private_enabled}, 公用={public_enabled}, 状态={status}")

            return {
                "rule_name": "防火墙状态检查",
                "status": status,
                "config_status": {
                    "domain_profile": domain_enabled,
                    "private_profile": private_enabled,
                    "public_profile": public_enabled,
                    "all_profiles_enabled": all_enabled,
                    "encoding_issue": '״̬' in output or 'ǽ' in output  # 标记编码问题
                },
                "status_details": status_details,
                "recommendation": recommendation
            }

        except Exception as e:
            return {
                "rule_name": "防火墙状态检查",
                "status": "检查失败",
                "config_status": {"error": str(e)},
                "status_details": [f"检查过程中发生错误: {str(e)}"],
                "recommendation": "防火墙状态需要手动验证，请运行 'netsh advfirewall show allprofiles' 命令检查"
            }

    @staticmethod
    def check_autostart_and_registry_hijack() -> Dict[str, Any]:
        """11. 检查自启项与注册表劫持（优化版：CMD批量排查）"""
        try:
            print("[规则11] 检查自启项与注册表劫持...")
            status_details = []
            suspicious_items = []

            # ========== 1. 检查启动目录（用dir /b批量获取文件，简化解析） ==========
            # 系统级+用户级启动目录（覆盖常见路径）
            startup_paths = [
                "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs\\Startup",
                f"C:\\Users\\{run_cmd_simple('echo %USERNAME%').strip()}\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\Startup"
            ]

            for path in startup_paths:
                # 用dir /b获取纯文件名列表（简化输出）
                files_output = run_cmd_simple(f'dir "{path}" /b 2>nul')
                if files_output and "找不到文件" not in files_output:
                    files = [f.strip() for f in files_output.split('\n') if f.strip()]
                    status_details.append(f"✓ 启动目录 {path} 包含 {len(files)} 个文件:")
                    for file in files:
                        status_details.append(f"  - {file}")
                        # 排除系统默认文件（如desktop.ini）
                        if "desktop.ini" not in file.lower() and "文件夹" not in file.lower():
                            suspicious_items.append({
                                "type": "启动目录文件",
                                "path": f"{path}\\{file}",
                                "reason": "非系统默认启动文件，可能为恶意自启"
                            })
                else:
                    status_details.append(f"✓ 启动目录 {path}: 无自启文件")

            # ========== 2. 检查注册表启动项（用reg query /s批量搜索，聚焦关键路径） ==========
            # 只保留高风险启动项路径（减少冗余检查）
            registry_run_paths = [
                "HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run",
                "HKEY_LOCAL_MACHINE\\SOFTWARE\\Windows\\CurrentVersion\\Run"
            ]

            for reg_path in registry_run_paths:
                # 直接查询所有值（/v *），简化解析
                reg_output = run_cmd_simple(f'reg query "{reg_path}" /v * 2>nul')
                if reg_output and "错误: 找不到项" not in reg_output:
                    # 提取名称和命令（忽略空行和路径行）
                    entries = [line.strip() for line in reg_output.split('\n') if line.strip() and "REG_SZ" in line]
                    status_details.append(f"✓ 注册表启动项 {reg_path} 包含 {len(entries)} 个条目:")
                    for entry in entries:
                        # 拆分名称和命令（取最后一列作为命令）
                        parts = entry.split()
                        name = parts[0]
                        cmd = ' '.join(parts[2:]) if len(parts) >= 3 else "未知命令"
                        status_details.append(f"  - 名称: {name}, 命令: {cmd}")
                        # 检测可疑命令特征（临时目录、脚本等）
                        if any(kw in cmd.lower() for kw in ["temp", "script", "powershell", "public"]):
                            suspicious_items.append({
                                "type": "注册表启动项",
                                "path": reg_path,
                                "name": name,
                                "cmd": cmd,
                                "reason": "命令含可疑路径/脚本，可能为恶意自启"
                            })
                else:
                    status_details.append(f"✓ 注册表启动项 {reg_path}: 无自启条目")

            # ========== 3. 检查注册表映像劫持（保留高效批量查询） ==========
            hijack_reg_path = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options"
            # 用reg query /s /f搜索所有Debugger值（批量排查核心）
            hijack_output = run_cmd_simple(f'reg query "{hijack_reg_path}" /s /f "Debugger" 2>nul')

            if hijack_output and "REG_SZ" in hijack_output:
                # 提取被劫持的程序和Debugger值
                hijacked_entries = [line.strip() for line in hijack_output.split('\n') if "REG_SZ" in line]
                status_details.append(f"✓ 映像劫持项 {hijack_reg_path} 发现 {len(hijacked_entries)} 个劫持配置:")
                for entry in hijacked_entries:
                    # 解析格式：路径\程序名    Debugger    REG_SZ    劫持命令
                    parts = entry.split()
                    prog_path = parts[0]
                    prog_name = prog_path.split('\\')[-1]  # 提取程序名
                    debugger = ' '.join(parts[3:]) if len(parts) >= 4 else "未知命令"
                    status_details.append(f"  - 程序: {prog_name}, 劫持命令: {debugger}")
                    # 重点检测系统关键程序
                    if any(prog in prog_name.lower() for prog in ["sethc.exe", "notepad.exe", "cmd.exe"]):
                        suspicious_items.append({
                            "type": "映像劫持",
                            "program": prog_name,
                            "debugger": debugger,
                            "reason": "系统关键程序被劫持，可能为恶意后门"
                        })
            else:
                status_details.append(f"✓ 映像劫持注册表项 {hijack_reg_path}: 无劫持配置")

            # ========== 汇总结果 ==========
            if suspicious_items:
                status_details.append("\n✗ 发现可疑项（建议处理）:")
                for i, item in enumerate(suspicious_items, 1):
                    status_details.append(f"  {i}. {item['type']}: {item['reason']}")
                    # 附加处理命令
                    if item["type"] == "启动目录文件":
                        status_details.append(f"     操作: del \"{item['path']}\" /f")
                    elif item["type"] == "注册表启动项":
                        status_details.append(f"     操作: reg delete \"{item['path']}\" /v \"{item['name']}\" /f")
                    else:
                        status_details.append(
                            f"     操作: reg delete \"{hijack_reg_path}\\{item['program']}\" /v Debugger /f")
            else:
                status_details.append("\n✓ 未发现可疑自启项或劫持配置")

            return {
                "rule_name": "自启项与注册表劫持检查",
                "status": "异常" if suspicious_items else "正常",
                "config_status": {
                    "suspicious_count": len(suspicious_items)
                },
                "status_details": status_details,
                "recommendation": "按操作指引排查可疑项" if suspicious_items else "配置正常"
            }
        except Exception as e:
            return {
                "rule_name": "自启项与注册表劫持检查",
                "status": "执行失败",
                "status_details": [f"错误: {str(e)}"],
                "recommendation": "请以管理员身份运行，检查命令权限"
            }

    @staticmethod
    def get_all_rules() -> List[callable]:
        """获取所有审计规则的函数列表"""
        return [
            WindowsAuditRules.check_password_policy,
            WindowsAuditRules.check_user_accounts,
            WindowsAuditRules.check_administrator_group,
            WindowsAuditRules.check_audit_logs,
            WindowsAuditRules.check_backup_status,
            WindowsAuditRules.check_updates_status,
            WindowsAuditRules.check_services_and_ports,
            WindowsAuditRules.check_scheduled_tasks,
            WindowsAuditRules.check_firewall_status,
            WindowsAuditRules.check_autostart_and_registry_hijack  # 新增规则
        ]


def run_cmd_simple(command: str) -> str:
    """简化的命令执行，避免编码问题"""
    try:
        result = subprocess.run(
            command,
            shell=True,
            capture_output=True,
            timeout=30
        )
        # 尝试多种编码方式
        encodings = ['gbk', 'utf-8', 'latin-1']
        for encoding in encodings:
            try:
                return result.stdout.decode(encoding, errors='replace')
            except UnicodeDecodeError:
                continue
        return result.stdout.decode('latin-1', errors='replace')
    except Exception as e:
        return f"Error: {str(e)}"